package com.chuangjiangx.member.basic.ddd.domain.model;

import com.chuangjiangx.dddbase.Entity;
import com.chuangjiangx.member.stored.ddd.domain.model.MbrStoredType;
import com.chuangjiangx.member.score.ddd.domain.model.MbrScoreType;
import com.chuangjiangx.member.stored.ddd.domain.exception.MemberPaymentException;
import lombok.Getter;
import lombok.Setter;

import java.math.BigDecimal;
import java.util.Date;

/**
 * 会员账户
 */
@Getter
@Setter
public class MbrAccount extends Entity<MbrAccountId> {

    /**
     * 会员id
     */
    private MemberId memberId;

    /**
     * 可用积分
     */
    private Long availableScore;

    /**
     * 累计积分
     */
    private Long totalScore;

    /**
     * 可用余额
     */
    private BigDecimal availableBalance;

    /**
     * 累计充值
     */
    private BigDecimal totalRechargeBalance;

    /**
     * 累计赠送
     */
    private BigDecimal totalGiveBalance;
    /**
     * 累计消费次数
     */
    private Integer totalConsumeCount;
    /**
     * 最后消费时间
     */
    private Date lastConsumeTime;

    public MbrAccount(MemberId memberId, Long availableScore, Long totalScore, BigDecimal availableBalance,
                      BigDecimal totalRechargeBalance, BigDecimal totalGiveBalance, Integer totalConsumeCount,
                      Date lastConsumeTime) {
        this.memberId = memberId;
        this.availableScore = availableScore;
        this.totalScore = totalScore;
        this.availableBalance = availableBalance;
        this.totalRechargeBalance = totalRechargeBalance;
        this.totalGiveBalance = totalGiveBalance;
        this.totalConsumeCount = totalConsumeCount;
        this.lastConsumeTime = lastConsumeTime;
    }

    public MbrAccount(Long availableScore, Long totalScore) {
        this.availableScore = availableScore;
        this.totalScore = totalScore;
    }

    public MbrAccount(MemberId memberId) {
        this.memberId = memberId;
        this.availableScore = 0L;
        this.totalScore = 0L;
        this.availableBalance = BigDecimal.ZERO;
        this.totalRechargeBalance = BigDecimal.ZERO;
        this.totalGiveBalance = BigDecimal.ZERO;
        this.totalConsumeCount = 0;
    }

    /**
     * 金额变动
     *
     * @param amount
     */
    public void changeMoney(BigDecimal amount, MbrStoredType type) {

        switch (type) {
            case RECHARGE:
                //可用余额++
                this.availableBalance = this.availableBalance.add(amount);
                //累计充值 ++
                this.totalRechargeBalance = this.totalRechargeBalance.add(amount);
                break;
            case RECHARGE_GIFT:
                //可用余额++
                this.availableBalance = this.availableBalance.add(amount);
                //累计赠送 ++
                this.totalGiveBalance = this.totalGiveBalance.add(amount);
                break;
            case REFUND:
                //可用余额++
                this.availableBalance = this.availableBalance.add(amount);
                break;
            case CONSUMER:
                if (this.availableBalance.compareTo(amount) < 0) {
                    throw new MemberPaymentException("800200", "会员储值账户余额不足");
                }
                //可用余额 --
                this.availableBalance = this.availableBalance.subtract(amount);
                //追后消费时间
                this.lastConsumeTime = new Date();
                //消费次数
                ++this.totalConsumeCount;
                break;
            default:
                break;
        }
    }


    /**
     * 积分变动
     */
    public void changeScore(Long score, MbrScoreType type) {
        switch (type) {
            case GIFT:
                //赠送
                //可用积分 ++
                this.availableScore += score;
                //累计积分 ++
                this.totalScore += score;
                //最后消费时间
                this.lastConsumeTime = new Date();
                //累计消费次数
                ++this.totalConsumeCount;
                break;
            case CONSUMER:
                //消费累计积分
                //可用积分 ++
                this.availableScore += score;
                //累计积分 ++
                this.totalScore += score;
                //最后消费时间
                this.lastConsumeTime = new Date();
                //累计消费次数
                ++this.totalConsumeCount;
                break;
            case REFUND:
                //退款扣除积分
                this.availableScore -= score;
                break;
            case EXCHANGE:
                //兑换扣除积分
                this.availableScore -= score;
                //最后消费时间
                this.lastConsumeTime = new Date();
                //累计消费次数
                ++this.totalConsumeCount;
                break;
            case CARD_GIFT:
                //可用积分 ++
                this.availableScore += score;
                //累计积分 ++
                this.totalScore += score;
            default:
                break;
        }
    }


    /**
     * 账户转移
     *
     * @param account
     */
    public void transferTo(MbrAccount account) {
        //可用积分
        account.availableScore = Long.sum(this.availableScore, account.availableScore);
        //总积分
        account.totalScore = Long.sum(this.totalScore, account.totalScore);
        //可用余额
        account.availableBalance = account.availableBalance.add(this.availableBalance);
        //总充值金额
        account.totalRechargeBalance = account.totalRechargeBalance.add(this.totalRechargeBalance);
        //总赠送金额
        account.totalGiveBalance = account.totalGiveBalance.add(this.totalGiveBalance);
        //总消费次数
        account.totalConsumeCount = Integer.sum(account.totalConsumeCount, this.totalConsumeCount);
        //最后消费时间
        Date t1 = account.getLastConsumeTime();
        Date t2 = this.getLastConsumeTime();
        Date lastConsumeDate = t1 == null ? t2 : (t2 == null ? null : t1.getTime() > t2.getTime() ? t1 : t2);
        account.lastConsumeTime = lastConsumeDate;
    }
}
